Frida Hook初探

前置

安装环境

想要快乐地进行frida hook,就需要先准备好一部安卓机(最好是真机)和adb环境,这一部分就不细说了。

安装frida的话,先在https://github.com/frida/frida/releases找好一个版本,然后下载手机对应架构的frida-server

比如我这里是

1666094521765.png

所以选择下载了frida-server-16.0.1-android-arm64

然后使用adb push ./frida-server-16.0.1-android-arm64 /data/local/tmp/将这个binary传到手机里

1666094632332.png

这样就是上传成功了,要用的时候只需要在adb起的shell中cd过去然后运行一下就行了(记得给运行权限)

在PC端用pip装一下frida这个库(frida版本要和安卓上的一样)

pip install frida-16.0.1.dev7-cp34-abi3-win_amd64.whl
pip install frida-tools

装好之后可以frida-ps -U测试一下

1666094885743.png

这样就是正常工作了

测试环境

简单测试一下脚本的使用

  • test.py
import frida
# print(frida.__version__)
device = frida.get_usb_device()
session = device.attach(22576)

print(device)
print(session)

with open("./hook.js") as f:
    script = session.create_script(f.read())
script.load()

input()
  • hook.js
console.log("hook success!")
Java.perform(
    function x(){
        console.log("Inside java perform function")
    }
)
  • 运行结果
1666095085571.png

利用

对原有方法进行覆盖

例题001

NewstarCTF上的一题,先把apk装到安卓机上

adb install ./apk.apk

浅浅运行一下

1666097355808.png

发现貌似逻辑不在MainActivity里,jadx打开果然发现了FlagActivity

所以需要指定加载到这里面来运行,在adb起的shell中执行

am start -n com.droidlearn.activity_travel/com.droidlearn.activity_travel.FlagActivity

然后就能看到进入了这个地方,但是需要点击10000次才能拿到flag,有点小离谱()

1666097661740.png

这里就可以用到frida来hook一下这个方法了

FlagActivity的源码在jadx中可以看到是这样的(图片不清楚的话可以放大看)

1666101531148.png

其中比较重要的片段是

...
private int cnt = 0;
static int access$004(FlagActivity flagActivity) {
	int i = flagActivity.cnt + 1;
    flagActivity.cnt = i;
    return i;
}
...
public void onCreate(Bundle bundle) {
...
	public void onClick(View view) {
		textView.setText(Integer.toString(FlagActivity.access$004(FlagActivity.this)));
    	if (FlagActivity.this.cnt >= 10000) {
        	Toast.makeText(FlagActivity.this, editText.getText().toString(), 0).show();
    	}
	}
...
}

每次监听到点击事件过后,就会使用access$004方法对cnt变量进行递增,并打印在屏幕上

那么我们可以hook到java层,重新实现access$004这个方法,让返回值直接大于10000

  • hook.js
Java.perform(
    function () {
        console.log("Inside java perform function");
        console.log("process pid = " + Process.id);
        var my_class = Java.use("com.droidlearn.activity_travel.FlagActivity");
        //console.log(my_class.access$004)
        my_class.access$004.implementation= function (x){
            console.log("cnt=" + x.cnt.value);
            x.cnt.value = 10001;
            console.log("cnt=" + x.cnt.value);
            return 10001;
        }
    }
);
  • exp.py
import frida

device = frida.get_usb_device()
session = device.attach(4180)

print(device)
print(session)

with open("./hook.js") as f:
    script = session.create_script(f.read())
script.load()

input()

成功修改cnt为10001,拿到flag

1666101428084.png

通过类名获取实例

例题001-REsolve

这里使用Java.choose(完整类名)的方法来解例题001

  • hook.js
// Java.perform方法:当 js 附加到目标的进程中时被执行,运行其中定义的函数
// Java.choose方法:通过完整类名,获取它的实例,从而对实例中的数据进行修改
// onMatch 对应的函数在命中一个实例的时候被调用,传入函数中的参数 instance 就是被命中的实例
// onComplete 函数会在所有实例遍历完毕之后被调用,可以做一些后续处理操作
Java.perform(
    function () {
        console.log("Inside java perform function");
        console.log("process pid = " + Process.id);
        var my_class = Java.use("com.droidlearn.activity_travel.FlagActivity");
        //console.log(my_class.access$004)
        // my_class.access$004.implementation= function (x){
        //     console.log("cnt=" + x.cnt.value);
        //     x.cnt.value = 10001;
        //     console.log("cnt=" + x.cnt.value);
        //     return 10001;
        // }

        Java.choose("com.droidlearn.activity_travel.FlagActivity",{
            onMatch:function(instance){
                console.log("cnt = " + instance.cnt.value);
                instance.cnt.value = 114514;
                console.log("cnt = " + instance.cnt.value);
            },
            onComplete:function(){
                console.log("finish")
            }
        });
    }
);
  • exp.py
import frida

device = frida.get_usb_device()
session = device.attach(4180)

print(device)
print(session)

with open("./hook.js") as f:
    script = session.create_script(f.read())
script.load()

input()

依然可以成功

1666102717859.png